<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>前端构建大型应用 | 被删的前端游乐场</title>
    <meta name="description" content="Just playing around">
    
    
    <link rel="preload" href="/front-end-playground/assets/css/0.styles.a683ed26.css" as="style"><link rel="preload" href="/front-end-playground/assets/js/app.e5cf4092.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/3.c853767c.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/2.eed49fdd.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/39.c364f2cb.js" as="script">
    <link rel="stylesheet" href="/front-end-playground/assets/css/0.styles.a683ed26.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/front-end-playground/" class="home-link router-link-active"><!----> <span class="site-name">被删的前端游乐场</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/front-end-playground/" class="nav-link">概述</a></div><div class="nav-item"><a href="/front-end-playground/front-end-basic/" class="nav-link router-link-active">前端基础</a></div><div class="nav-item"><a href="/front-end-playground/vue/" class="nav-link">Vue学习</a></div><div class="nav-item"><a href="/front-end-playground/wxapp/" class="nav-link">小程序学习</a></div><div class="nav-item"><a href="/front-end-playground/front-end-others/" class="nav-link">百家齐放</a></div><div class="nav-item"><a href="/front-end-playground/front-end-addon/" class="nav-link">前端的进击</a></div><div class="nav-item"><a href="/front-end-playground/faq.html" class="nav-link">FAQ</a></div> <a href="https://github.com/godbasin/front-end-playground" target="_blank" rel="noopener noreferrer" class="repo-link">
    Github
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/front-end-playground/" class="nav-link">概述</a></div><div class="nav-item"><a href="/front-end-playground/front-end-basic/" class="nav-link router-link-active">前端基础</a></div><div class="nav-item"><a href="/front-end-playground/vue/" class="nav-link">Vue学习</a></div><div class="nav-item"><a href="/front-end-playground/wxapp/" class="nav-link">小程序学习</a></div><div class="nav-item"><a href="/front-end-playground/front-end-others/" class="nav-link">百家齐放</a></div><div class="nav-item"><a href="/front-end-playground/front-end-addon/" class="nav-link">前端的进击</a></div><div class="nav-item"><a href="/front-end-playground/faq.html" class="nav-link">FAQ</a></div> <a href="https://github.com/godbasin/front-end-playground" target="_blank" rel="noopener noreferrer" class="repo-link">
    Github
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0" style="padding-top:;"><!----> <p class="sidebar-heading"><span>前端入门</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0" style="padding-top:10px;"><div class="kitty-main" data-v-0cd75e06><span class="stand" data-v-0cd75e06></span> <div class="cat" data-v-0cd75e06><div class="body" data-v-0cd75e06></div> <div class="head" data-v-0cd75e06><div class="ear" data-v-0cd75e06></div> <div class="ear" data-v-0cd75e06></div></div> <div class="face" data-v-0cd75e06><div class="nose" data-v-0cd75e06></div> <div class="whisker-container" data-v-0cd75e06><div class="whisker" data-v-0cd75e06></div> <div class="whisker" data-v-0cd75e06></div></div> <div class="whisker-container" data-v-0cd75e06><div class="whisker" data-v-0cd75e06></div> <div class="whisker" data-v-0cd75e06></div></div></div> <div class="tail-container" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06></div></div></div></div></div></div></div></div></div></div> <p class="sidebar-heading open"><span>前端深入理解</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/front-end-playground/front-end-basic/understanding/build-application.html" class="active sidebar-link">前端构建大型应用</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/build-application.html#框架选择" class="sidebar-link">框架选择</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/build-application.html#项目代码结构" class="sidebar-link">项目代码结构</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/build-application.html#代码流程规范" class="sidebar-link">代码流程规范</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/build-application.html#路由管理" class="sidebar-link">路由管理</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/build-application.html#抽象和组件化" class="sidebar-link">抽象和组件化</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/build-application.html#状态和数据管理" class="sidebar-link">状态和数据管理</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/build-application.html#代码打包" class="sidebar-link">代码打包</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/understanding/build-application.html#编写可测试代码" class="sidebar-link">编写可测试代码</a></li></ul></li><li><a href="/front-end-playground/front-end-basic/understanding/component-communication-with-data-model.html" class="sidebar-link">数据抽离与数据管理</a></li><li><a href="/front-end-playground/front-end-basic/understanding/component-with-configuration.html" class="sidebar-link">组件配置化</a></li><li><a href="/front-end-playground/front-end-basic/understanding/component-with-itself.html" class="sidebar-link">一个组件的自我修养</a></li><li><a href="/front-end-playground/front-end-basic/understanding/app-component-isolation.html" class="sidebar-link">页面区块化与应用组件化</a></li><li><a href="/front-end-playground/front-end-basic/understanding/template-engine.html" class="sidebar-link">前端模板引擎</a></li><li><a href="/front-end-playground/front-end-basic/understanding/dialogue-abstraction.html" class="sidebar-link">对话抽象</a></li><li><a href="/front-end-playground/front-end-basic/understanding/data-driven-or-event-driven.html" class="sidebar-link">前端思维转变--从事件驱动到数据驱动</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><p>与其说是构建大型应用，或许更多地是常用的应用构建吧。很多时候我们的项目在搭建的时候通常都不会定位为大型项目，但我们还是需要考虑到拓展性，或者说是在当项目开始变得较难维护的时候，要进行调整的一些方面。</p> <h1 id="项目设计"><a href="#项目设计" aria-hidden="true" class="header-anchor">#</a> 项目设计</h1> <p>在项目开始之前，我们需要做一系列的规划，像项目的定位（to B/C）、大小，像框架和工具的选型，还有很重要的一点是，项目和团队规范。</p> <h2 id="框架选择"><a href="#框架选择" aria-hidden="true" class="header-anchor">#</a> 框架选择</h2> <p>通常来说，框架选择是准备项目的第一步。</p> <p>说到框架，目前主流三大框架 Angular、React 和 Vue，先从个人理解来看看这三个框架。</p> <h3 id="angular"><a href="#angular" aria-hidden="true" class="header-anchor">#</a> Angular</h3> <p>这里的 Angular 是指 Angular 2.0+ 版本，v1.0 我们通常称之为 AngularJS，目前已经不更新了，建议大家还是使用 Angular。</p> <p>Angular 相对 React 和 Vue，最初的设计是针对大型应用来进行的。要是你认识 JAVA 的话，像依赖注入这一套你会觉得很熟悉。当然到了 v2.0 以上的版本由于加入了很多的语法糖，看起来 AngularJS 和 Angular 相差很远，但是最核心的依赖注入模式还是相似的。</p> <p>关于 Angular 各个版本的对比，大家可以参考下<a href="https://godbasin.github.io/2017/07/01/about-angular-from-1-to-4/" target="_blank" rel="noopener noreferrer">《谈谈 Angular--从 Angular1 到 Angular4》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> 以及<a href="https://github.com/godbasin/godbasin.github.io/issues/1" target="_blank" rel="noopener noreferrer">《重新认识 Angular》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>。</p> <p>项目中使用 Angular，最大的体验感受则是项目有完备的结构和规范，新加入的成员能很快地通过复制粘贴完成功能的开发。身边有人说过，好的架构设计，能让高级程序员和初入门的程序员写出相似的代码，这样对于整体管理和项目的维护有非常好的体验。</p> <p>至于 Vue 和 React，它们更多是小巧的模板框架，也可以通过灵活搭配路由、状态管理等工具，达到大型应用的管理。目前来说，社区也有比较好的解决方案，官方也有出相关的脚手架来快速构建应用。</p> <p>很多人说 Angular 难上手，其实主要在于开始的项目搭建、以及 Angular 独有的一套设计方案的理解。但是依赖注入的设计方式，我们几乎不用考虑很多数据和状态管理的问题。当然脏检查的方式曾经也带来性能问题，后面在加入树状的模块化、Zone.js 之后，即使没有虚拟 DOM，性能也是有大大的提升。</p> <h3 id="react"><a href="#react" aria-hidden="true" class="header-anchor">#</a> React</h3> <p>本人接触的 React 项目不是很多，但是 jsx、虚拟 DOM、函数式编程的设计，带来的震撼和冲击还是很大的。</p> <p>React 相对 Angular 最大的优势是轻量，或许其实这么比较不大对，因为 React/Vue 和 Angular 不一样，Angular 是整套的解决方案，而 React/Vue 则是项目搭建中灵魂使用的前端模板工具。</p> <div class="language-cmd extra-class"><pre class="language-text"><code>Angular = React + react-router + Redux/Flux/Mobx = Vue + vue-router + Vuex/Redux
</code></pre></div><p>虚拟 DOM 主要解决了什么，它的原理又是怎样的，这些会涉及到浏览器的页面渲染原理，包括 DOM Tree、CSS Ruler Tree、Rendering Tree、Repaint、Reflow 等等，你需要去理解虚拟 DOM 为何能带来性能的提升。</p> <p>类似这样的，你会在使用 React 的时候，接触到很多好的设计，去引领你进行更深入的思考。函数式编程的方式，也会不同程度地拓展你的思考方式，遇到问题的时候，能有更多的解决办法。</p> <p>至于社区建设，其实三大主流开源框架的社区都相当完善了。</p> <h3 id="vue"><a href="#vue" aria-hidden="true" class="header-anchor">#</a> Vue</h3> <p>如果你熟悉 Angular 以及 React，你会发现 Vue 的使用，其实很多地方像是两个的结合体。</p> <p>Vue 最大的特点是上手简单，不管是框架的设计和文档，都对新手极其友好。但是这并不代表它只是个简单的框架，当你需要实现一些更加深入的自定义功能时，你会发现它其实也有很好的功能支持。如果你还认为它只是把 Angular 和 React 的优势结合，在你深入使用甚至阅读源码的时候，你会慢慢发现里面的一些自己的思考，真的是个很棒的框架。</p> <p>如果说你是个新手，那么 Vue 会是较好的选择。相比另外两个框架，Vue 最初的社区缺陷现在也早已不再是问题了，相关的脚手架、配套工具也都很完善。</p> <h3 id="开源框架？"><a href="#开源框架？" aria-hidden="true" class="header-anchor">#</a> 开源框架？</h3> <p>使用开源框架的好处是，有着完整详细的文档，同时有问题也能通过 issues 和 <a href="https://stackoverflow.com" target="_blank" rel="noopener noreferrer">Stack Overflow<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> 来查找。</p> <p>更多时候，我们选择一个框架，需要考虑项目大小、定位。**技术选型更多的在于团队，你要考虑这个团队的能力、大家对各个框架的熟悉程度、是否有强烈的倾向。**或者有能力的团队，也可以选择相对小众的框架。</p> <p>当然也有些小伙伴喜欢自己造轮子，不过你们要记得，造轮子是要负责任的，你需要提供友好的文档和 API 给他人，不然对项目的维护来说，简直就是毁灭性的体验。</p> <p>还有在生产环境，尽量使用 release 版本吧。那段将 Angular2-beta 升级到 Angular4-rc 版本的日子，真的不堪回想。</p> <p>有些人喜欢捣鼓新东西，个人的体验是，我们尽量在对这些新技术有较好地把握之后，再尝试一点点加入我们的项目里。项目尤其是工程项目，大多数是解决某些问题，我们需要在满足业务和项目维护性的同时，来做一些新的尝试。</p> <h2 id="项目代码结构"><a href="#项目代码结构" aria-hidden="true" class="header-anchor">#</a> 项目代码结构</h2> <p>个人认为，好的项目代码结构会大大提升项目的维护性。同时我们可以提供友好的说明，以便其他成员理解项目和快速定位。</p> <p>这里贴出个人比较偏好的结构：</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token comment"># Angular</span>
│
├── src/                              <span class="token comment"># 项目代码存放位置</span>
│   │
│   ├── app/                          <span class="token comment"># app相关代码</span>
│   │   ├── modules/                  <span class="token comment"># 业务模块</span>
│   │   ├── shared/                   <span class="token comment"># 公用组件/服务等</span>
│   │   └── container/                <span class="token comment"># Angular应用入口文件（路由、启动模块等）</span>
│   │
│   ├── assets                        <span class="token comment"># 相关资源</span>
│   ├── environments/                 <span class="token comment"># 环境相关配置</span>
│   │
│   ├── index.html                    <span class="token comment"># 主页面</span>
│   └── main.ts                       <span class="token comment"># angular启动文件</span>
│
├── dist/                             <span class="token comment"># 存放编译打包生成文件</span>
├── e2e/                              <span class="token comment"># e2e测试相关文件</span>
├── .gitignore                        <span class="token comment"># Git上传相关配置</span>
├── package.json                      <span class="token comment"># npm相关配置</span>
├── README.md                         <span class="token comment"># 说明文档</span>
└── xxx.json/xxx.js/.xxxx             <span class="token comment"># 其他配置文档</span>
</code></pre></div><div class="language-bash extra-class"><pre class="language-bash"><code><span class="token comment"># Vue</span>
│
├── src/                              <span class="token comment"># 项目代码存放位置</span>
│   │
│   ├── app/                          <span class="token comment"># app相关代码</span>
│   │
│   ├── components/                   <span class="token comment"># 公用组件</span>
│   ├── router/                       <span class="token comment"># 路由配置</span>
│   ├── store/                        <span class="token comment"># store</span>
│   │
│   ├── index.html                    <span class="token comment"># 主页面</span>
│   ├── main.js                       <span class="token comment"># 启动文件</span>
│   <span class="token operator">|</span>
│   └── <span class="token punctuation">..</span>.                           <span class="token comment"># 其他文件</span>
│
├── dist/                             <span class="token comment"># 存放编译打包生成文件</span>
├── config/build/                     <span class="token comment"># 项目构建相关配置</span>
├── .gitignore                        <span class="token comment"># Git上传相关配置</span>
├── package.json                      <span class="token comment"># npm相关配置</span>
├── README.md                         <span class="token comment"># 说明文档</span>
└── xxx.json/xxx.js/.xxxx             <span class="token comment"># 其他配置文档</span>
</code></pre></div><p>其实有一点比较重要，就是公共组件、工具等同类的文件，放置一起维护会比较好。而且还有个小 tips，我们可以在搭建项目的时候，在 README.md 里面描述下该项目下的代码和文件结构。</p> <h2 id="代码流程规范"><a href="#代码流程规范" aria-hidden="true" class="header-anchor">#</a> 代码流程规范</h2> <p>代码规范其实是团队合作中最重要的地方，使用相同的代码规范，会大大减少我们接手别人代码时候卧槽的次数。</p> <p>好的写码习惯很重要，命名习惯、适当的注释，会对代码的可读性有很大的提升。但是习惯是每个人都不一样，所以在此之上，我们需要有这样统一的代码规范。</p> <p>一些工具可以很好地协助我们，像 Eslint、Tslint 等，加上代码的打包工具协助，可以把一些规范强行标准化，来获取代码的统一性。还有像 prettier 这样的工具，能自动在打包的时候帮我们进行代码规范化。</p> <p>除了这些简单的什么驼峰啊、全等啊、单引双引等基础的规范，其实更重要的是<strong>流程规范</strong>。最基础的是改动公共库或是公共组件的时候，需要进行 code review。通常我们使用 Git 维护代码，这样在合并或是版本控制上有更好的体验。</p> <p>但其实最重要的还是沟通，沟通是一个团队里必不可少同时很容易出问题的地方，要学会沟通方式、表达方式。</p> <h1 id="大型应用优化"><a href="#大型应用优化" aria-hidden="true" class="header-anchor">#</a> 大型应用优化</h1> <p>说到大型应用，其实像页面加载性能、构建打包等地方，我们都可以适当进行优化。</p> <h2 id="路由管理"><a href="#路由管理" aria-hidden="true" class="header-anchor">#</a> 路由管理</h2> <p>路由管理其实主要是当我们的项目变大方便管理，同时为了项目体验问题而引入的解决方案。毕竟我们产品设计都比较成熟，对用户来说刷新页面会丢掉页面状态，这样的体验是在是太糟糕了。</p> <p>我们在规划项目路由的时候，会推动我们对项目业务、功能区块化有更加深入的认识和理解。同时对我们的项目结构规划也有很大的帮助，我们可以根据路由来放置我们的代码文件，有了这样的约定，我们在维护他人代码的时候，便能迅速地定位到对应的位置。</p> <p>路由管理现在很多框架都有配套的工具库，已经有很多完善的解决方案了，这里不多说。</p> <h2 id="抽象和组件化"><a href="#抽象和组件化" aria-hidden="true" class="header-anchor">#</a> 抽象和组件化</h2> <p>在我们开始写重复的代码、或是进行较多的复制粘贴的时候，大概我们需要考虑对组件进行适当的抽象了。</p> <p>好的抽象能大量减少重复代码，同时对项目整体有更深入的理解。坏的抽象会增加项目的复杂度，同时降低了代码的可读性和维护性。所以关键在于适度，好的办法是结合产品和业务来进行抽象，例如一个播放器组件、日历组件、快速导航栏、快捷菜单等组件封装，便于多次使用。</p> <p>而组件的抽象相关，可以参加<a href="/front-end-playground/understanding/component-with-itself.html">《一个组件的自我修养》</a>。</p> <p>同时，我们也需要把一些相同的方法抽离，封装成通用的工具库，像常用的时间转换、字符串处理、http 请求等，都可以单独拎出来维护。</p> <h2 id="状态和数据管理"><a href="#状态和数据管理" aria-hidden="true" class="header-anchor">#</a> 状态和数据管理</h2> <p>我们的应用里，多数会面临组件的某些状态和数据相互影响、相互依赖的问题。</p> <p>现在也有比较成熟的解决方案和状态管理工具，像 Vuex、Redux、Mobx 等，我们需要结合自身的框架和业务场景来使用。像父子组件的交互、应用内无直接管理的数据状态共享、事件的传递等，也都需要结合实际适当地使用。</p> <h2 id="代码打包"><a href="#代码打包" aria-hidden="true" class="header-anchor">#</a> 代码打包</h2> <p>当我们的应用变得很大，为了提升首屏加载的体验，我们需要对代码进行分块打包。</p> <p>一般来说，不同的框架有不同的异步加载解决方案，同时可以结合打包工具（Webpack 等）进行分块打包。我们可以把首屏相关的东西打包到 bundle，其他模块分块打包到 chunk，来在需要的时候再进行加载。</p> <h3 id="路由异步加载"><a href="#路由异步加载" aria-hidden="true" class="header-anchor">#</a> 路由异步加载</h3> <p>通常情况下，我们会结合路由进行分块打包，路由管理工具大部分都支持异步加载。</p> <p>我们可以根据自己需要，来打包成多个文件，在路由进入的时候才获取和加载。Vue 的话可参考<a href="https://godbasin.github.io/2018/01/28/vue2-notes-17-lazyload-chunk/" target="_blank" rel="noopener noreferrer">《Vue2 使用笔记 17--路由懒加载》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>，打包效果像这样：</p> <p><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/1515581250%281%29.png" alt="image"></p> <h3 id="webpack-分块打包"><a href="#webpack-分块打包" aria-hidden="true" class="header-anchor">#</a> Webpack 分块打包</h3> <p>使用 Webpack 的话，可以用：</p> <ul><li>CommonsChunkPlugin：提取代码中的公共模块，然后将公共模块打包到一个独立的文件中，以便在其他的入口和模块中使用</li> <li>ExtractTextPlugin：可以将样式或其他从 js 中抽出，生成单独的<code>.css</code>样式文件</li> <li><code>require.ensure()</code> <ul><li>webpack 在编译时，会静态地解析代码中的<code>require.ensure()</code>，同时将模块添加到一个分开的 chunk 当中</li> <li>这个新的 chunk 会被 webpack 通过 jsonp 来按需加载</li></ul></li></ul> <h3 id="source-map"><a href="#source-map" aria-hidden="true" class="header-anchor">#</a> Source map</h3> <p>这里需要讲一下，Source map 就是一个信息文件，里面储存着位置信息。也就是说，转换后的代码的每一个位置，所对应的转换前的位置。有了它，出错的时候，除错工具将直接显示原始代码，而不是转换后的代码。这无疑给开发者带来了很大方便。</p> <p>关于 Source map，可参考阮大神的<a href="http://www.ruanyifeng.com/blog/2013/01/javascript_source_map.html" target="_blank" rel="noopener noreferrer">《JavaScript Source Map 详解》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>。</p> <p>在开发环境下，还能通过 Chrome 匹配源文件进行在线 debug 和修复源码。大家也可以自行搜索下，尤其我们需要在浏览器上直接调试 CSS 并生效的时候，体验真的很棒。</p> <h3 id="tree-shaking"><a href="#tree-shaking" aria-hidden="true" class="header-anchor">#</a> Tree-shaking</h3> <p>不知道大家熟悉 Tree-shaking 不，我们在引入一些开源代码或是公共库的时候，其实大部分时间我们都只是使用其中里面的一小部分代码。</p> <p>Tree-shaking 通常指按需加载，即没有被引用的模块不会被打包进来，减少我们的包大小，缩小应用的加载时间，呈现给用户更佳的体验。</p> <p>最初是 <a href="http://www.rollupjs.com/" target="_blank" rel="noopener noreferrer">Rollup<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> 提出并实现。Rollup 静态分析代码中的 import，并将排除任何未实际使用的代码。这允许我们架构于现有工具和模块之上，而不会增加额外的依赖或使项目的大小膨胀。</p> <p>同时在 Webpack 2 里也加入了 Tree-shaking 新特性。至于目前的一些情况，也可以参考下<a href="https://segmentfault.com/a/1190000012794598" target="_blank" rel="noopener noreferrer">《你的 Tree-Shaking 并没什么卵用》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>这篇文章。</p> <h2 id="编写可测试代码"><a href="#编写可测试代码" aria-hidden="true" class="header-anchor">#</a> 编写可测试代码</h2> <p>测试的重要性不用多说，有了测试，我们每次功能调整和重构的时候，心会踏实很多吧。</p> <p>但是目前大部分情况是，项目中功能的快速迭代、开发工作量饱满等原因，导致甚至单元测试这种都很少编写。Emmmmm。。。所以这里不多讲述，因为本人也没有太多经验。</p> <h1 id="结束语"><a href="#结束语" aria-hidden="true" class="header-anchor">#</a> 结束语</h1> <p>项目的维护永远是程序员的大头，多是前人种树后人乘凉。但是很多时候，大家会为了一时的方便，对代码规范比较随意，就导致了我们经常看到有人讨论“继承来的代码”。<br>
或许相比新技术的研究和造轮子，有个好的写码习惯、提高项目维护性并不能带来短期的利益，但是其实身为程序员，还是要对自己写的东西负责任的呢。</p></div> <!----> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/godbasin/front-end-playground/edit/sourcecode/docs/front-end-basic/understanding/build-application.md" target="_blank" rel="noopener noreferrer">帮阿猪改善此页面！</a> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div> <!----> <blockquote>部分文章中使用了一些网站的截图，如果涉及侵权，请告诉我删一下谢谢~</blockquote> <div style="margin-top:30px;"><div class="el-row" style="margin-left:-10px;margin-right:-10px;"><div class="el-col el-col-24 el-col-sm-0 el-col-md-2 el-col-lg-4" style="padding-left:10px;padding-right:10px;display:block;"><div style="width:1px;height:1px;"></div></div> <div class="el-col el-col-24 el-col-sm-24 el-col-md-18 el-col-lg-16" style="padding-left:10px;padding-right:10px;"><div class="el-card box-card is-always-shadow"><div class="el-card__header"><div class="clearfix"><span>温馨提示喵</span></div></div><div class="el-card__body"> <div class="el-row" style="margin-left:-10px;margin-right:-10px;"><div class="el-col el-col-24 el-col-xs-24 el-col-sm-12" style="padding-left:10px;padding-right:10px;"><div class="el-image"><div class="image-slot"><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/assets/img/loading.gif" style="width:100%;"></div><!----></div></div> <div class="el-col el-col-24 el-col-xs-24 el-col-sm-12" style="padding-left:10px;padding-right:10px;"><div class="copyright-text"><div>本文版权归作者所有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。</div> <div>出处：被删的前端游乐场</div> <div>作者：<a href="https://github.com/godbasin" target="_blank">被删</a></div></div></div></div></div></div></div></div></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/front-end-playground/front-end-basic/front-end/front-end-10.html" class="prev">
          10. 理解 HTTP 协议
        </a></span> <span class="next"><a href="/front-end-playground/front-end-basic/understanding/component-communication-with-data-model.html">
          数据抽离与数据管理
        </a>
        →
      </span></p></div>  <div class="gitalk-container theme-default-content"><div id="gitalk-container" class="content"></div></div></main> <div id="kitty-container"><span><div role="tooltip" id="el-popover-5462" aria-hidden="true" class="el-popover el-popper" style="width:undefinedpx;display:none;"><!----><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/2code2.jpg" class="image"> <div class="text">牡羊猪的猫粮罐</div> </div><div id="kitty" style="background:url(https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/assets/img/kitty1.svg);"></div></span> <div class="el-dialog__wrapper" style="display:none;"><div role="dialog" aria-modal="true" aria-label="牡羊猪是这样渐渐胖成猪的喵（点击图片可以切换噢）" class="el-dialog" style="margin-top:15vh;"><div class="el-dialog__header"><span class="el-dialog__title">牡羊猪是这样渐渐胖成猪的喵（点击图片可以切换噢）</span><button type="button" aria-label="Close" class="el-dialog__headerbtn"><i class="el-dialog__close el-icon el-icon-close"></i></button></div><!----><!----></div></div></div></div><div class="global-ui"></div></div>
    <script src="/front-end-playground/assets/js/app.e5cf4092.js" defer></script><script src="/front-end-playground/assets/js/3.c853767c.js" defer></script><script src="/front-end-playground/assets/js/2.eed49fdd.js" defer></script><script src="/front-end-playground/assets/js/39.c364f2cb.js" defer></script>
  </body>
</html>
